'use strict';

/* GENERICS STORES */

app.factory("imageStore", ["$q", "$timeout", "$indexeddb", "imageService", function ($q, $timeout, $indexeddb, imageService) {
    function ImageStore() {
        var self = this;
        self.maxSize = 50;
        self.count = 0;

        $indexeddb.getAll("image").then(function(data){
            self.count = data.length;
        });
    };

    ImageStore.prototype.isFull = function(){
        return this.count >= self.maxSize;
    };

    ImageStore.prototype.get = function (src) {
        var self = this;
        //console.log("start imageStore.get",src);
        return $indexeddb.get("image", src).then(function(content){
            if(content) {
                $timeout(function(){
                    content.dates.request = new Date().toJSON();
                    return $indexeddb.put("image", content);
                });
            }
            //console.log("end imageStore.get",src);
            return content;    
        }).catch(function (error) {
            return null;
        });
    };

    ImageStore.prototype.getOrInsert = function (src) {
        var self = this;
        return self.get(src).then(function(content){
            if(content) return content;
            return self.insert(src);
        });
    };

    ImageStore.prototype.save = function (src) {
        var self = this;
        return self.update(src).then(function(content){
           if(content) return content;
           return self.insert(src);
        });
    }

    ImageStore.prototype.update = function (src) {
        var self = this;
        return this.get(src).then(function(content){
            if(!content) return null;
            content.count = content.count + 1; //increment usage
            content.dates.save = new Date().toJSON();
            $indexeddb.put("image", content).then(function(){
                //console.log("imageStore.update",src);
               return content; 
            });
        });
    };
    
    ImageStore.prototype.insert = function (src) {
        var self = this;
        return imageService.toDataURL(src).then(function (image) {
            var content = {
                src: src,
                count: 1,
                image: image,
                dates: {
                    save: new Date().toJSON(),
                    request: new Date().toJSON()
                }
            };
            
            return $timeout(function(){
                return self.shrink().then(function(){
                    return $indexeddb.add("image", content).then(function(){
                        //console.log("imageStore.insert",src);
                        self.count = self.count + 1;
                    });
                });
            }, 10);

            //console.log("end imageStore.insert",src);
            return countent;
        });
    };

    ImageStore.prototype.remove = function (src) {
        return this.get(src).then(function(content){
            if(!content) return;
            if(content.count <= 1)  {
                return $indexeddb.remove("image", src).then(function(){  //delete image because nobody use it
                    self.count = self.count - 1; 
                });
            }
            content.count =  content.count - 1; //decrement count and update object in cache
            return $indexeddb.put("image", content);
        });
    };

    ImageStore.prototype.clear = function () { 
        return $indexeddb.clear("image");
    };

    ImageStore.prototype.shrink = function () {
        var self = this;
        //console.log("start shrink");
        return $timeout(function(){
            if(!self.isFull()) return;
            return $indexeddb.index("image", "request").then(function(i){
                return i.first(null, "prev").then(function(data){
                    return $indexeddb.remove("image", data.src).then(function(){
                        return self.shrink();
                    });
                });
            });
        });
    };

    return new ImageStore();
} ]);

app.factory("Store", ["$q", "$indexeddb", "$timeout", function ($q, $indexeddb, $timeout) {
    function Store(options) {
        this.table = options.table;
        this.maxSize = options.maxSize || 20;
        this.imageStore = options.imageStore;
    };

    Store.prototype.get = function (key) { //key is optional. if undefined -> use first() instead of get(key)
        var self = this;
        return $timeout(function(){
            if(!self.table) return null;
            if(!key) throw new Error("key is empty.");
            return $indexeddb.get(self.table, key)
        }).catch(function (error) {
            return null;
        });
    };

    Store.prototype.clear = function () {
        return $indexeddb.clear(this.table);
    };

    Store.prototype.remove = function (key) { //key is optional. if undefined -> use first() instead of get(key)
        var self = this;
        if(!key) return self.clear();
        else return $indexeddb.remove(self.table, key);
    };

    Store.prototype.getAll = function () {
        var self = this;
        return $timeout(function(){
            if(!self.table) return [];
            return $indexeddb.getAll(self.table).catch(function (error) {
                return [];
            });
        });
    };

    Store.prototype.save = function (data, key) { //key is optional. if undefined -> use first() instead of get(key)
        var self = this;
        return $timeout(function(){
            if(!self.table) return;
            if(!data) throw new Error("Data is empty.");

            return self.get(key).then(function(old) {
                var promise = null;
                if(alert) promise = $indexeddb.put(self.table, data);
                else promise = $indexeddb.add(self.table, data); ////TODO limited cache size with shrink
                return promise.then(function(){
                    return self.imageStore.replaceAll(old ? [old] : [], [data]);
                });
            });
        });
    };

    Store.prototype.saveAll = function (data) {
        var self = this;
        return $timeout(function(){
            if(!self.table) return;
            return $indexeddb.getAll(self.table).then(function(alerts){
                return $indexeddb.clear(self.table).then(function () {
                    var limitedData = data.slice(0, self.maxSize); 
                    return $indexeddb.addAll(self.table, limitedData).then(function () {
                        return self.imageStore.replaceAll(alerts, limitedData);
                    });
                });
            });
        });
    };

    return Store;
} ]);

/* DEDICATED IMAGE STORES */

app.factory("alertImageStore", ["$q", "imageStore", function ($q, imageStore) {
    function AlertImageStore() {
    };

    AlertImageStore.prototype.replaceAll = function(oldItems, newItems){
        var promises = [];
        newItems.forEach(function (item) {
            promises.push(imageStore.save(item.shop.picto.src)); //save all icons
        });
        return $q.all(promises).then(function(){
            var promises = [];
            oldItems.forEach(function (item) {
                promises.push(imageStore.remove(item.shop.picto.src)); //delete old image all icons
            });
            return $q.all(promises);
        });
    };

    return new AlertImageStore();
} ]);

app.factory("shopImageStore", ["$q", "imageStore", function ($q, imageStore) {
    function ShopImageStore() {
    };

    ShopImageStore.prototype.replaceAll = function(oldItems, newItems){
        var promises = [];
        newItems.forEach(function (item) {
            promises.push(imageStore.save(item.picto.src)); //save all icons
        });
        return $q.all(promises).then(function(){
            var promises = [];
            oldItems.forEach(function (item) {
                promises.push(imageStore.remove(item.picto.src)); //delete old image all icons
            });
            return $q.all(promises);
        });
    };

    return new ShopImageStore();
} ]);

app.factory("userImageStore", ["$q", "imageStore", function ($q, imageStore) {
    function UserImageStore() {
    };

    UserImageStore.prototype.replaceAll = function(oldItems, newItems){
        var promises = [];
        newItems.forEach(function (item) {
            promises.push(imageStore.save(item.picto.src)); //save all icons
        });
        return $q.all(promises).then(function(){
            var promises = [];
            oldItems.forEach(function (item) {
                promises.push(imageStore.remove(item.picto.src)); //delete old image all icons
            });
            return $q.all(promises);
        });
    };

    return new UserImageStore();
} ]);

/* DEDICATED STORES */

app.factory("homeStore", ["Store", "alertImageStore", function (Store, alertImageStore) {
    return new Store({ 
        table: "home",
        imageStore: alertImageStore
    });
} ]);

app.factory("likeStore", ["Store", "alertImageStore", function (Store, alertImageStore) {
    return new Store({ 
        table: "like",
        imageStore: alertImageStore
    });
} ]);

app.factory("newsStore", ["Store", "alertImageStore", function (Store, alertImageStore) {
    return new Store({ 
        table: "news",
        imageStore: alertImageStore
    });
} ]);

app.factory("subscriptionStore", ["Store", "shopImageStore", function (Store, shopImageStore) {
    return new Store({ 
        table: "subscription",
        imageStore: shopImageStore
    });
} ]);

app.factory("accountStore", ["Store", "userImageStore", function (Store, userImageStore) {
    return new Store({ 
        table: "account",
        imageStore: userImageStore
    });
} ]);

app.factory("emptyAccountStore", ["Store", function (Store) {
    return new Store();
} ]);

app.factory("shopStore", ["Store", "shopImageStore", function (Store, shopImageStore) {
    return new Store({ 
        table: "shop",
        imageStore: shopImageStore
    });
} ]);

app.factory("alertStore", ["Store", "alertImageStore", function (Store, alertImageStore) {
    return new Store({ 
        table: "alert",
        imageStore: alertImageStore
    });
} ]);
